/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Optimizacion;

import java.util.ArrayList;
import Data.*;

/**
 *
 * @author REI
 */
public class OptimizacionBloque extends ListaBloques{
    
    Tipo_funcion tf = new Tipo_funcion();
    int numero = 0;

    public ListaBloques crear_bloque(ArrayList lista) {//recibe la lista de lineas de codigo del cuerpo de una funcion
        ListaBloques bloques = new ListaBloques();
        ArrayList lineas_codigo = new ArrayList();
        NodoBloque nodo = new NodoBloque();

        if (!lista.isEmpty()) {
            if (lista.size() >= 2) {
                for (int i = 0; i < lista.size(); i++) {
                    String linea1 = lista.get(i).toString().trim();
                    if (linea1.indexOf(":") != -1) {//si es linea de Etiqueta
                        if (!lineas_codigo.isEmpty() || !nodo.getEtiquetas().isEmpty()) {//si trae lineas de codigo
                            nodo.setLineas_codigo(new ArrayList(lineas_codigo));
                            nodo.setNumero(numero++);
                            bloques.add(nodo);//se agrega el bloque
                            nodo = new NodoBloque();
                            lineas_codigo.clear();
                        }
                        ArrayList temp = new ArrayList();
                        if (linea1.indexOf(",") != -1) {//si es listado de etiquetas
                            String[] etqS = linea1.replace(":", "").trim().split(",");
                            for (int j = 0; j < etqS.length; j++) {
                                temp.add(etqS[j].trim());
                            }
                            nodo.setEtiquetas(new ArrayList(temp));//se agrega la lista de etiquetas
                        } else {//es una sola etiqueta
                            temp.add(linea1.replace(":", "").trim());
                            nodo.setEtiquetas(new ArrayList(temp));//se agrega la lista de etiquetas
                        }
                        temp.clear();
                    } else {
                        if (linea1.toUpperCase().startsWith("GOTO")) {//si es un salto de linea
                            //se obtiene la etiqueta del goto, y se asigna a la etqF
                            nodo.setEtqF(get_nombre_etq(linea1));
                            lineas_codigo.add(linea1);
                            nodo.setLineas_codigo(new ArrayList(lineas_codigo));
                            nodo.setNumero(numero++);
                            bloques.add(nodo);
                            nodo = new NodoBloque();
                            lineas_codigo.clear();
                        } else {
                            if (linea1.toUpperCase().startsWith("IF")||linea1.toUpperCase().startsWith("IF_NOT")) {
                                
                                 
                                
                                
                                nodo.setEtqV(get_nombre_etq(linea1));
                                lineas_codigo.add(linea1);
                                String linea2 = lista.get(i + 1).toString().trim();
                                if (!linea2.toUpperCase().startsWith("GOTO") && linea2.indexOf(":") == -1 ) {//si NO es un salto de linea y tampoco etiquetas
                                    nodo.setNumero(numero++);
                                    nodo.setLineas_codigo(new ArrayList(lineas_codigo));
                                    bloques.add(nodo);
                                    nodo = new NodoBloque();
                                    lineas_codigo.clear();
                                }
                            } else {//si es cualquier otra linea, ya se ASIG_VAR;, CALL_FX
                                
                                               
                                
                                lineas_codigo.add(linea1);
                            }
                        }

                    }

                    if ((i + 1) == lista.size()) {
                        nodo.setLineas_codigo(new ArrayList(lineas_codigo));
                        nodo.setNumero(numero++);
                        bloques.add(nodo);
                        return bloques;
                    }

                }
            } else {
                //si solo viene una linea de codigo, significa q a una variable global se le asigno un valor
                //de ahi cualquier otro caso, siempre seran de 2 o mas lineas
                bloques.add(new NodoBloque(lista, numero++));
            }
        }

        return bloques;
    }

    public boolean subExpresiones_comunes(ListaBloques bloque) {
        NodoBloque aux = bloque.getInicio();
        boolean cambio = false;
        while (aux != null) {
            ArrayList lista = aux.getLineas_codigo();
            for (int i = 0; i < lista.size() - 1; i++) {
                String linea_base = lista.get(i).toString().trim();
                if (linea_base.indexOf("#") == -1 &&linea_base.indexOf("()") == -1 && !linea_base.toUpperCase().startsWith("GOTO") && !linea_base.toUpperCase().startsWith("HEAP") && !linea_base.toUpperCase().startsWith("PILA") && !linea_base.toUpperCase().startsWith("IF")&& !linea_base.toUpperCase().startsWith("IF_NOT")&& !linea_base.toUpperCase().startsWith("USING")&& !linea_base.toUpperCase().startsWith("COUT")&& !linea_base.toUpperCase().startsWith("INT")&& !linea_base.toUpperCase().startsWith("FLOAT")&& !linea_base.toUpperCase().startsWith("TX")&& !linea_base.toUpperCase().startsWith("RETURN")&& !linea_base.toUpperCase().startsWith("OFS") && !linea_base.toUpperCase().startsWith("STD")&& !linea_base.toUpperCase().startsWith("CHAR")) {
                    
                    String[] div1 = linea_base.split("=");
                    String valor = div1[1].trim();
                    String temporal = div1[0].trim();
                    if (!valor.toUpperCase().startsWith("HEAP") && !valor.toUpperCase().startsWith("PILA")) {//se verifica que no sea un acceso al HEAP o PILA
                        if (valor.indexOf("+") != -1 || valor.indexOf("-") != -1 || valor.indexOf("*") != -1 || valor.indexOf("/") != -1 || valor.indexOf("%") != -1|| valor.indexOf("^") == -1) {//se verifica que sea una expresion
                            //si del lado derecho del =  no es una operacion, indica q es un temporal o variable
                            for (int j = i + 1; j < lista.size(); j++) {
                                String linea2 = lista.get(j).toString().trim();
                                if (linea2.indexOf("#") == -1&&linea2.indexOf("()") == -1 && !linea2.toUpperCase().startsWith("GOTO") && !linea2.toUpperCase().startsWith("IF")&& !linea2.toUpperCase().startsWith("IF_NOT")&& !linea2.toUpperCase().startsWith("USING")&& !linea2.toUpperCase().startsWith("COUT")&& !linea2.toUpperCase().startsWith("INT")&& !linea2.toUpperCase().startsWith("FLOAT")&& !linea2.toUpperCase().startsWith("TX")&& !linea2.toUpperCase().startsWith("RETURN")&& !linea2.toUpperCase().startsWith("OFS") && !linea2.toUpperCase().startsWith("STD")&& !linea2.toUpperCase().startsWith("CHAR")) {
                                 
                                    
                                    String[] div2 = linea2.split("=");
                                    
                                    String temp2 = div2[0].trim();
                                    String valor2 = div2[1].trim();
                                    
                                    if(valor.contains(temp2))
                                    {
                                        j = lista.size();
                                        System.out.println(valor +" = "+ temp2);
                                        System.out.println("no se permite el cambio");
                                    }
                                    else if (valor.compareTo(valor2) == 0) {
                                        lista.set(j, div2[0] + "= " + temporal + ";");
                                        cambio = true;
                                    }
                                    
                                }
                            }
                        }
                    }

                }
            }
            aux = aux.getSiguiente();
        }
        return cambio;
    }
    
   
    public boolean propagacion_de_copias(ListaBloques bloque) {
        NodoBloque aux = bloque.getInicio();
        boolean cambio = false;
        while (aux != null) {
            ArrayList lista = aux.getLineas_codigo();
            for (int i = 0; i < lista.size(); i++) {
                String linea_base = lista.get(i).toString().trim();
                if (linea_base.indexOf("#") == -1&&linea_base.indexOf("()") == -1 && !linea_base.toUpperCase().startsWith("GOTO") && !linea_base.toUpperCase().startsWith("HEAP") && !linea_base.toUpperCase().startsWith("PILA") && !linea_base.toUpperCase().startsWith("IF")&& !linea_base.toUpperCase().startsWith("IF_NOT")&& !linea_base.toUpperCase().startsWith("USING")&& !linea_base.toUpperCase().startsWith("COUT")&& !linea_base.toUpperCase().startsWith("INT")&& !linea_base.toUpperCase().startsWith("FLOAT")&& !linea_base.toUpperCase().startsWith("TX")&& !linea_base.toUpperCase().startsWith("RETURN")&& !linea_base.toUpperCase().startsWith("OFS") && !linea_base.toUpperCase().startsWith("STD")&& !linea_base.toUpperCase().startsWith("CHAR")) {
                    
                    String[] div1 = linea_base.split("=");
                    String valor = div1[1].trim();
                    String temporal = div1[0].trim();
                    if (!valor.toUpperCase().startsWith("HEAP") && !valor.toUpperCase().startsWith("PILA")) {//se verifica que no sea un acceso al HEAP o PILA
                        if (valor.indexOf("+") == -1 && valor.indexOf(" - ") == -1 && valor.indexOf("*") == -1 && valor.indexOf("/") == -1 && valor.indexOf("%") == -1&& valor.indexOf("^") == -1) {//se verifica que sea una expresion
                            //si del lado derecho del =  no es una operacion, indica q es un temporal o variable
                            for (int j = i + 1; j < lista.size(); j++) {
                                String linea2 = lista.get(j).toString().trim();
                                if (linea2.indexOf("#") == -1&&linea2.indexOf("()") == -1 && !linea2.toUpperCase().startsWith("GOTO")&&!linea2.toUpperCase().startsWith("USING")&& !linea2.toUpperCase().startsWith("INT")&& !linea2.toUpperCase().startsWith("FLOAT")&& !linea2.toUpperCase().startsWith("COUT")&& !linea2.toUpperCase().startsWith("TX") && !linea2.toUpperCase().startsWith("RETURN")&& !linea2.toUpperCase().startsWith("OFS") && !linea2.toUpperCase().startsWith("STD")&& !linea2.toUpperCase().startsWith("CHAR")) {
                                    if (linea2.toUpperCase().startsWith("IF")||linea2.toUpperCase().startsWith("IF_NOT")) {
                                        if (linea2.indexOf(temporal + " ") != -1) {
                                            lista.set(j, linea2.replace(temporal + " ", valor.replace(";", "")));
                                            cambio = true;
                                        }
                                    } else {
                                        
                                        String[] div2 = linea2.split("=");

                                        String temp2 = div2[0].trim();
                                        if (temporal.compareTo(temp2) == 0) {//si el temporal es igual a temp2, indica que el temporal esta cambiando de valor
                                            //unas lineas mas abajo, por lo tanto se forma el recorrido del bloque para esa linea que se estaba comparando
                                            j = lista.size();
                                        } else {
                                            if (linea2.indexOf(temporal + "") != -1) {
                                                lista.set(j, linea2.replace(temporal + "", valor.replace(";", "")));
                                                cambio = true;
                                            }
                                        }
                                    }
                                }
                            }

                            //aqui elimino valor_iz == valor_der
                            if (linea_base.indexOf(" = ") != -1) {
                                String[] var = linea_base.split("=");
                                if (var[0].trim().compareTo(var[1].replace(";", "").trim()) == 0) {
                                    lista.remove(i);
//                                    i = i - 1;
                                }
                            }
                        }
                    }

                }
            }
            aux = aux.getSiguiente();
        }
        return cambio;
    }

    public boolean eliminacion_de_codigo_inactivo(ListaBloques bloque, int bloque_globales) {
        NodoBloque aux = bloque.getInicio();
        boolean cambio = false;
        while (aux != null) {
            ArrayList lista = aux.getLineas_codigo();
            for (int i = 0; i < lista.size(); i++) {
                String linea_base = lista.get(i).toString().trim();
                if (linea_base.indexOf("#") == -1&&linea_base.indexOf("()") == -1 && !linea_base.toUpperCase().startsWith("GOTO") && !linea_base.toUpperCase().startsWith("HEAP") && !linea_base.toUpperCase().startsWith("PILA") && !linea_base.toUpperCase().startsWith("IF")&& !linea_base.toUpperCase().startsWith("IF_NOT")&& !linea_base.toUpperCase().startsWith("COUT")&& !linea_base.toUpperCase().startsWith("USING")&& !linea_base.toUpperCase().startsWith("H = H")&&!linea_base.toUpperCase().startsWith("P = P")&&!linea_base.toUpperCase().startsWith("FLOAT")&&!linea_base.toUpperCase().startsWith("INT")&& !linea_base.toUpperCase().startsWith("TX")&& !linea_base.toUpperCase().startsWith("RETURN")&& !linea_base.toUpperCase().startsWith("OFS") && !linea_base.toUpperCase().startsWith("STD")&& !linea_base.toUpperCase().startsWith("CHAR")) {
                    
                    String[] div1 = linea_base.split("=");
                    System.out.println(linea_base);
                    String valor = div1[1].trim();
                    String temporal = div1[0].trim();
                    if (!valor.toUpperCase().startsWith("HEAP") && !valor.toUpperCase().startsWith("PILA")) {//se verifica que no sea un acceso al HEAP o PILA
                        if (valor.indexOf("+") == -1 && valor.indexOf(" - ") == -1 && valor.indexOf("*") == -1 && valor.indexOf("/") == -1 && valor.indexOf("%") == -1&& valor.indexOf("^") == -1) {//se verifica que sea una expresion
                            //si del lado derecho del =  no es una operacion, indica q es un temporal o variable
                            boolean utilizado = false;
                            for (int j = i + 1; j < lista.size(); j++) {
                                String lineaX = lista.get(j).toString().trim();
                                if (lineaX.indexOf("#") == -1&&lineaX.indexOf("()") == -1 && !lineaX.toUpperCase().startsWith("GOTO")&& !lineaX.toUpperCase().startsWith("COUT")&&!lineaX.toUpperCase().startsWith("FLOAT")&&!lineaX.toUpperCase().startsWith("INT")&& !lineaX.toUpperCase().startsWith("TX")&& !lineaX.toUpperCase().startsWith("RETURN")&& !lineaX.toUpperCase().startsWith("OFS") && !lineaX.toUpperCase().startsWith("STD")&& !lineaX.toUpperCase().startsWith("CHAR")) {
                                    if (lineaX.toUpperCase().startsWith("IF")||lineaX.toUpperCase().startsWith("IF_NOT")) {
                                        if (lineaX.indexOf(temporal + " ") != -1) {//si en la condicion del IF, se utiliza el temporal
                                            //se sale del recorrido y continua con la siguiente linea I
                                            utilizado = true;
                                            j = lista.size();
                                        }
                                    }
                                    else if(lineaX.toUpperCase().startsWith("USING")){
                                        
                                        if (lineaX.indexOf(temporal + "") != -1) {//si en la condicion del IF, se utiliza el temporal
                                            //se sale del recorrido y continua con la siguiente linea I
                                            utilizado = true;
                                            j = lista.size();
                                        }
                                        
                                    
                                    }else {
                                        
                                        String[] div2 = lineaX.split("=");
                                        String valorX = div2[1].trim();
                                        String tempX = div2[0].trim();

                                        if (temporal.compareTo(tempX) == 0) {//si los temporales son iguales
                                            if (valorX.indexOf(temporal + "") == -1) {//si el temporal no esta siendo utilizado en el valor de la lineaX
                                                //se elimina la linea del temporal, ya q esta inactivo
                                                    //se comprueba q el temporal, no sea una variable global
                                                    
                                                        utilizado = true;
                                                        j = lista.size();
                                                    
                                            }
                                        } else {
                                            if (valorX.indexOf(temporal + "") != -1) {//si el temporal esta siendo utilizado en el valor de la lineaX
                                                utilizado = true;
                                                j = lista.size();//se forza la salida
                                            }
                                            
                                        }
                                    }
                                }
                            }
                            if (utilizado == false) {
                                
                                        lista.remove(i);
                                        i = i - 1;
                                    
                                
                            }
                        }
                    }

                }
            }
            aux = aux.getSiguiente();
        }
        return cambio;
    }

    public String get_nombre_etq(String linea) {
        return linea.substring(linea.toUpperCase().indexOf("GOTO") + 4, linea.length()).trim();
    }
    
}
